/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package abricots.game;

import abricots.MyLog;
import abricots.net.common.NetUtils;
import com.esotericsoftware.minlog.Log;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

/**
 *
 * @author charly
 */
public class TimeManager {

    private final static MyLog log = new MyLog(TimeManager.class.getSimpleName(), Log.LEVEL_DEBUG);
    public static final int DRAW_LAG = 100;
    private long gameStartTime = -1;
    private long lastUpdateTime = -1;
    private long previousUpdateTime = -1;
    private final List<Long> intermediateTimes;
    private long lastKeyFrame;
    private long nextKeyFrame;

    public TimeManager() {
        intermediateTimes = Collections.synchronizedList(new ArrayList<Long>());
    }

    public long getGameTime() {
        if (gameStartTime < 0) {
            return -1;
        }
        return System.currentTimeMillis() - gameStartTime;
    }

    /**
     * Returns a new update Time. Subsequent call to
     * getLast... will return values based on this
     * @return 
     */
    public void newUpdate() {
        log.trace("New update");
        if (gameStartTime < 0) {
            log.trace(" Game not started..");
            return;
        }
        previousUpdateTime = lastUpdateTime;
        lastUpdateTime = System.currentTimeMillis() - gameStartTime;
        log.trace(" Last: " + lastUpdateTime + " ; previous: " + previousUpdateTime);

        // Check keyFrames
        if (previousUpdateTime >= 0) {
            long timeBeforeLastUpdateTime = lastUpdateTime % NetUtils.SERVER_FRAME_DURATION;
            long lastKeyFrameTime = lastUpdateTime - timeBeforeLastUpdateTime;
            nextKeyFrame = lastKeyFrameTime + NetUtils.SERVER_FRAME_DURATION;
            if (lastKeyFrameTime <= lastUpdateTime && lastKeyFrameTime > previousUpdateTime) {
                lastKeyFrame = lastKeyFrameTime;
                addIntermediateTime(lastKeyFrame);
            }
        }
        addIntermediateTime(lastUpdateTime);
    }

    public long getLastUpdateTime() {
        return lastUpdateTime;
    }

    public long getPreviousUpdateTime() {
        return previousUpdateTime;
    }

    public long getLastKeyFrame() {
        return lastKeyFrame;
    }

    public long getNextKeyFrame() {
        return nextKeyFrame;
    }

    public void setGameStartTime(long gameStartTime) {
        this.gameStartTime = gameStartTime;
    }

    public void addIntermediateTime(long time) {
        synchronized (intermediateTimes) {
            if (intermediateTimes.contains(time)) {
                return;
            }
            intermediateTimes.add(time);
            Collections.sort(intermediateTimes);
            log.trace(" Added intermediate time " + time);
        }
    }

    public List<Long> getTimes() {
        synchronized (intermediateTimes) {
            return new ArrayList<Long>(intermediateTimes);
        }
    }

    public void clearTimesBefore(long gameTime) {
        lastKeyFrame = -1;
        synchronized (intermediateTimes) {
            Iterator<Long> it = intermediateTimes.iterator();
            while (it.hasNext()) {
                long time = it.next();
                if (time <= gameTime) {
                    it.remove();
                } else {
                    break;
                }
            }
        }
        log.trace("Cleared before " + gameTime);
    }
}
